package com.ssy.lingxi.after.sale.serviceimpl;

import cn.hutool.core.date.DateUtil;
import com.ssy.lingxi.after.sale.api.model.vo.request.VerifyVO;
import com.ssy.lingxi.after.sale.entity.ReturnGoodsDO;
import com.ssy.lingxi.after.sale.model.constant.*;
import com.ssy.lingxi.after.sale.model.vo.request.ReturnGoodsPageVO;
import com.ssy.lingxi.after.sale.model.vo.response.ReturnGoodsQueryVO;
import com.ssy.lingxi.after.sale.repository.ReturnGoodsDetailRepository;
import com.ssy.lingxi.after.sale.repository.ReturnGoodsRepository;
import com.ssy.lingxi.after.sale.service.IFeignService;
import com.ssy.lingxi.after.sale.service.IReturnGoodsPlatformService;
import com.ssy.lingxi.after.sale.utils.ProcessUtil;
import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.order.api.model.vo.request.OrderAfterSaleVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 *  平台后台-售后管理
 * @author ds
 * @version 2.0.0
 * @date 2021/06/17
 */
@Slf4j
@Service
public class ReturnGoodsPlatformServiceImpl extends BaseReturnGoodsServiceImpl implements IReturnGoodsPlatformService {


    @Resource
    private ReturnGoodsRepository returnRepository;
    @Resource
    private IFeignService feignService;
    @Resource
    private ReturnGoodsDetailRepository returnGoodsDetailRepository;

    private List<ReturnGoodsQueryVO> ConvertReturnGoodsApplyQueryVO(List<ReturnGoodsDO> returnGoodsDOList) {
        List<ReturnGoodsQueryVO> resultList = null;
        if (returnGoodsDOList != null) {
            resultList = returnGoodsDOList.stream().map(r -> {
                ReturnGoodsQueryVO queryVO = new ReturnGoodsQueryVO();
                queryVO.setReturnId(r.getId());
                queryVO.setApplyNo(r.getApplyNo());
                queryVO.setApplyAbstract(r.getApplyAbstract());
                queryVO.setConsumerName(r.getConsumerName());
                queryVO.setSupplierName(r.getSupplierName());
                queryVO.setRefundAmount(r.getRefundAmount());
                queryVO.setRefunded(r.getRefunded());
                queryVO.setApplyTime(DateUtil.format(DateUtil.date(r.getApplyTime()), "yyyy-MM-dd HH:mm"));
                queryVO.setInnerStatus(r.getInnerStatus());
                if (ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode().equals(r.getOuterStatus())) {
                    queryVO.setInnerStatusName("待确认申请单");
                }
                queryVO.setOuterStatus(r.getOuterStatus());
                queryVO.setOuterStatusName(ReturnGoodsOuterStatusEnum.getMessage(r.getOuterStatus()));
                queryVO.setReturnBatch(r.getReturnBatch());
                queryVO.setReturnDeliveryId(r.getReturnDeliveryId());
                queryVO.setReturnDeliveryNo(r.getReturnDeliveryNo());
                queryVO.setReturnStorageId(r.getReturnStorageId());
                queryVO.setReturnStorageNo(r.getReturnStorageNo());
                queryVO.setReturnLogisticsId(r.getReturnLogisticsId());
                queryVO.setReturnLogisticsNo(r.getReturnLogisticsNo());
                queryVO.setReturnGoodsAddress(r.getReturnGoodsAddress());
                queryVO.setMemberId(r.getMemberId());
                queryVO.setRoleId(r.getRoleId());
                queryVO.setParentMemberId(r.getParentMemberId());
                queryVO.setParentMemberRoleId(r.getParentMemberRoleId());
                queryVO.setShopId(r.getShopId());
                queryVO.setShopLogo(r.getShopLogo());
                queryVO.setShopName(r.getShopName());
                return queryVO;
            }).collect(Collectors.toList());
        }

        return resultList;
    }

    private Wrapper<PageData<ReturnGoodsQueryVO>> pageList(ReturnGoodsPageVO pageVO) {

        // step 1: 组装查询条件
        Specification<ReturnGoodsDO> spec =  (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            if (pageVO.getOuterStatus() != null
                    && !pageVO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("outerStatus").as(Integer.class), pageVO.getOuterStatus()));
            }
            if (pageVO.getInnerStatus() != null
                    && !pageVO.getInnerStatus().equals(ReturnGoodsInnerStatusEnum.ALL.getCode())) {
                list.add(criteriaBuilder.equal(root.get("innerStatus").as(Integer.class), pageVO.getInnerStatus()));
            }
            if (StringUtils.hasLength(pageVO.getStartTime())) {
                list.add(criteriaBuilder.greaterThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getStartTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getEndTime())) {
                list.add(criteriaBuilder.lessThan(root.get("applyTime").as(Long.class), DateUtil.parse(pageVO.getEndTime()).getTime()));
            }
            if (StringUtils.hasLength(pageVO.getApplyNo())) {
                list.add(criteriaBuilder.like(root.get("applyNo").as(String.class), "%" + pageVO.getApplyNo().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getApplyAbstract())) {
                list.add(criteriaBuilder.like(root.get("applyAbstract").as(String.class), "%" + pageVO.getApplyAbstract().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getConsumerName())) {
                list.add(criteriaBuilder.like(root.get("consumerName").as(String.class), "%" + pageVO.getConsumerName().trim() + "%"));
            }
            if (StringUtils.hasLength(pageVO.getSupplierName())) {
                list.add(criteriaBuilder.like(root.get("supplierName").as(String.class), "%" + pageVO.getSupplierName().trim() + "%"));
            }

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        // step 2: 组装分页参数
        Pageable page = PageRequest.of(pageVO.getCurrent() - 1, pageVO.getPageSize(), Sort.by("applyTime").descending());

        // step 3: 分页查询数据
        Page<ReturnGoodsDO> result = returnRepository.findAll(spec, page);

        // step 4: 组装返回数据
        List<ReturnGoodsQueryVO> resultList = ConvertReturnGoodsApplyQueryVO(result.getContent());

        return Wrapper.success(new PageData<>(result.getTotalElements(), resultList));
    }

    @Override
    public Wrapper<PageData<ReturnGoodsQueryVO>> pageToBeVerifyByPlatform(UserLoginCacheDTO user, ReturnGoodsPageVO pageVO) {
        ReturnGoodsPageVO returnGoodsPageVO = new ReturnGoodsPageVO();
        returnGoodsPageVO.setCurrent(pageVO.getCurrent());
        returnGoodsPageVO.setPageSize(pageVO.getPageSize());
        returnGoodsPageVO.setApplyNo(pageVO.getApplyNo());
        returnGoodsPageVO.setApplyAbstract(pageVO.getApplyAbstract());
        returnGoodsPageVO.setStartTime(pageVO.getStartTime());
        returnGoodsPageVO.setEndTime(pageVO.getEndTime());
        returnGoodsPageVO.setOuterStatus(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode());
        returnGoodsPageVO.setConsumerName(pageVO.getConsumerName());
        returnGoodsPageVO.setSupplierName(pageVO.getSupplierName());
        return pageList(returnGoodsPageVO);
    }

    @Override
    public Wrapper<Void> verifyByPlatform(UserLoginCacheDTO user, VerifyVO verifyVO) {
        if (verifyVO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_VERIFY_PARAM_EMPTY);
        }
        ReturnGoodsDO returnDO = returnRepository.findById(verifyVO.getApplyId()).orElse(null);
        if (returnDO == null) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_NOT_EXIST);
        }
        // 外部状态为待平台确认申请单，才允许审核
        if (!returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.TO_BE_PLATFORM_CONFIRM.getCode())) {
            throw new BusinessException(ResponseCode.AS_RETURN_GOODS_UN_ALLOW_VERIFY);
        }

        // 新增平台内部流转记录
        String innerStatusName = ReturnGoodsInnerStatusEnum.getMessage(returnDO.getInnerStatus());
        addInnerWorkflowRecord(user, returnDO.getId(), returnDO.getInnerStatus(), innerStatusName, ReturnGoodsActionEnum.PLATFORM_CONFIRM.getMessage(), verifyVO.getOpinion());


        Integer oldStatus=returnDO.getOuterStatus();
        // 外部流转：确认退货申请单这里直接业务逻辑处理，不进行工作流流转
        if (CommonBooleanEnum.NO.getCode().equals(verifyVO.getIsPass())) {
            returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode());
            //还原退货数量
            List<OrderAfterSaleVO> afterSales= buildUpdateOrderParamBySave(returnDO.getId());
            Wrapper<?> updateOrderWrapper = feignService.orderProductDetailsUpdate(afterSales);
            if (updateOrderWrapper == null || updateOrderWrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
                throw new BusinessException(ResponseCode.AS_UPDATE_RETURN_GOODS_COUNT_ERROR);
            }
        } else {
            returnDO.setOuterStatus(ReturnGoodsOuterStatusEnum.ACCEPT_APPLY.getCode());
            //活动订单，feign更新销量数据 售后数量不参与活动统计
            //updateMarketingActivityGoodsSales(returnDO.getId(),user);
        }

        // 新增供应商外部流转记录
        String statusName = ReturnGoodsOuterStatusEnum.UN_ACCEPT_APPLY.getCode().equals(returnDO.getOuterStatus()) ? "不接受申请" : "接收申请";
        addOuterWorkflowRecord(user, returnDO.getId(), returnDO.getOuterStatus(), ReturnGoodsActionEnum.CONFIRM.getMessage(), "【"+statusName+"】"+verifyVO.getOpinion());

        // 售后退货处理-待平台确认退货申请单-1
        commonReduceOperateNotice(returnDO,oldStatus);

        // 确认完退货申请后，且外部状态为接受申请时，进入下一步流转环节
        if (returnDO.getOuterStatus().equals(ReturnGoodsOuterStatusEnum.ACCEPT_APPLY.getCode())) {

            // 检查是否需要退货，如不需要退货，则跳过退货流程
            Boolean isExists = returnGoodsDetailRepository.existsByReturnIdAndIsNeedReturn(returnDO.getId(), CommonBooleanEnum.YES.getCode());
            Integer agree = TaskAgreeEnum.REFUSE.getCode();
            if (isExists) {
                agree = TaskAgreeEnum.AGREE.getCode();
            }else{
                //如果非合同流程
                if(!ProcessUtil.isContractOfReturnGoods(returnDO.getOuterTaskType())){
                    //如果无需退款
                    if(returnDO.getRefundAmount()==0){
                        agree = TaskAgreeEnum.AGREE_CONDITION2.getCode();
                    }
                }
            }
            // 执行外部流转
            completeOuterTask(returnDO, agree);
            Integer status = returnDO.getOuterStatus();

            // 如果外部状态为：待新增退货发货单，则设置内部状态为：待新增退货发货单
            if (ReturnGoodsOuterStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_ADD_RETURN_DELIVERY_GOODS.getCode());
                // 售后退货申请待新增退货发货单+1
            }
            // 如果外部状态为：待退款，则设置内部状态为：待退款
            else if (ReturnGoodsOuterStatusEnum.TO_BE_REFUND.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_REFUND.getCode());
                // 售后退货处理(供应商)待退款+1
                // 售后退货处理(平台账户)待退款+1
            }
            // 如果外部状态为：待退货发货,则设置内部状态为:待确认退货发货
            else if (ReturnGoodsOuterStatusEnum.TO_BE_RETURN_DELIVERY_GOODS.getCode().equals(status)) {
                returnDO.setInnerStatus(ReturnGoodsInnerStatusEnum.TO_BE_CONFIRM_RETURN_DELIVERY_GOODS.getCode());
                // 售后退货申请待退货发货+1
            } else if(ReturnGoodsOuterStatusEnum.TO_BE_CONFIRM_COMPLETE.getCode().equals(status)){
                //无退款+无退货的->待确认售后完成
                // 待确认售后完成+1
            }
        }
        //添加通知与首页统计计数
        commonSystemMessageAndIncreaseOperateNotice(returnDO,returnDO.getOuterStatus());
        //保存
        returnRepository.saveAndFlush(returnDO);
        return Wrapper.success();
    }
}
